/**
 *
 */
package com.kjcxlab.avcviewer.audio;


import com.kjcxlab.avcviewer.util.Constants;

/**
 * @author efhkklm
 */
public class AacRtpPacket {
    private byte[] packet = null;
    private int packetLength = 0;

    public boolean setPacket(byte[] data) {
        boolean ret = false;
        if (data.length > 4) {
            this.packet = data;
            ret = true;
        }

        return ret;
    }

    public byte[] getPacket() {
        return packet;
    }

    // version (V): 2 bits
    // padding (P): 1 bit
    // extension (X): 1 bit
    // CSRC count (CC): 4 bits
    // marker (M): 1 bit
    // payload type (PT): 7 bits
    // sequence number: 16 bits
    // timestamp: 32 bits
    // SSRC: 32 bits
    // CSRC list: 0 to 15 items, 32 bits each

    /**
     * Gets the version (V)
     **/
    public final int getVersion() {
        if (packetLength >= 12)
            return (packet[0] >> 6 & 0x03);
        else
            return 0; // broken packet
    }

    // check mark bit
    public final boolean getMark() {
        return ((((int) packet[1] & 0xFF) >>> 7) == 1);
    }

    /**
     * Whether has padding (P)
     */
    public final boolean hasPadding() {
        if (packetLength >= 12)
            return Constants.getBit(packet[0], 5);
        else
            return false; // broken packet
    }

    /**
     * Whether has extension (X)
     */
    public final boolean hasExtension() {
        if (packetLength >= 12)
            return Constants.getBit(packet[0], 4);
        else
            return false; // broken packet
    }

    /**
     * Gets the CSCR count (CC)
     */
    public final int getCscrCount() {
        if (packetLength >= 12)
            return (packet[0] & 0x0F);
        else
            return 0; // broken packet
    }

    /**
     * Gets the payload type (PT)
     */
    public final int getPayloadType() {
        int paytype = 0;
        if (packetLength >= 12)
            paytype = (packet[1] & 0x7F);
        else
            paytype = -1; // broken packet
        return paytype;
    }

    /**
     * Gets the sequence number
     */
    public final int getSequenceNumber() {
        int seq = 0;
        if (packetLength >= 12)
            seq = Constants.getInt(packet, 2, 4);
        else
            seq = 0; // broken packet
        return seq;
    }

    /**
     * Gets the timestamp
     */
    public final long getTimestamp() {
        if (packetLength >= 12)
            return Constants.getLong(packet, 4, 8);
        else
            return 0; // broken packet
    }

    /**
     * Gets the SSCR
     */
    public final long getSscr() {
        if (packetLength >= 12)
            return Constants.getLong(packet, 8, 12);
        else
            return 0; // broken packet
    }

    /**
     * Gets the CSCR list
     */
    public final long[] getCscrList() {
        int cc = getCscrCount();
        long[] cscr = new long[cc];
        for (int i = 0; i < cc; i++)
            cscr[i] = Constants.getLong(packet, 12 + 4 * i, 16 + 4 * i);
        return cscr;
    }

    public int getAuHeaderLength() {
        if (packet.length > 14)
            return ((((int) packet[12] & 0xFF) << 8) | ((int) packet[13] & 0xFF)) / 16;
        return 0;
    }
    //FIXME:Bug here about array index range
    public int getFrameLength() {
        int i = getAuHeaderLength();
        int j = 0;
        int len = 0;
        for (j = 0; j < i; j++) {
            len += (((int) (packet[14 + j * 2] & 0xFF) << 5) | ((int) (packet[14 + j * 2 + 1] & 0xFF) >> 3));
        }

        //System.out.println("header len:" + i + "---" + j);
        return len;
    }

    /**
     * Gets payload
     */
    public final byte[] getPayload() {

        int len = 0;

        if ((len = packet.length - Constants.RTP_HEADER_LENGTH) <= 0) {
            return null;
        }

        byte[] payload = new byte[len];
        System.arraycopy(packet, packet.length - len, payload, 0, len);

        return payload;
    }
}
